﻿using SharpDX.Multimedia;
using SharpDX.XAudio2;
using System;
using System.Composition;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;

namespace Padsurface.Audio.Wave
{
    [Export]
    public class WaveFileOutput : IDisposable
    {
        private readonly StorageFile _storageFile;
        private Lazy<SourceVoice> _sourceVoice;

        private AudioEngine _xaudio2Engine;
        private Stream _fileStream;
        private SoundStream _soundStream;
        private AudioBuffer _audioBuffer;

        public string Name 
        { 
            get 
            { 
                return _storageFile.DisplayName; 
            }
        }

        public string FilePath 
        {
            get
            {
                return _storageFile.Path;
            }
        }

        public WaveFileOutput(StorageFile storageFile)
        {
            if (storageFile == null) throw new ArgumentNullException("storageFile");
            
            _storageFile = storageFile;
            _sourceVoice = new Lazy<SourceVoice>(Initialize);
        }

        private SourceVoice Initialize()
        {
            _fileStream = _storageFile.OpenStreamForReadAsync().Result;
            _soundStream = new SoundStream(_fileStream);
            _audioBuffer = new AudioBuffer(_soundStream.ToDataStream());
            _xaudio2Engine = AudioEngine.GetInstance();

            return new SourceVoice(_xaudio2Engine.XAudio2, _soundStream.Format, true);
        }

        public void StartPlaying()
        {
            _sourceVoice.Value.Stop();
            _sourceVoice.Value.FlushSourceBuffers();
            _sourceVoice.Value.SubmitSourceBuffer(_audioBuffer, _soundStream.DecodedPacketsInfo);
            _sourceVoice.Value.Start();
        }

        public void StopPlaying()
        {
            _sourceVoice.Value.Stop();
        }

        public void Dispose()
        {
            if(_fileStream != null)
                _fileStream.Dispose();

            if(_soundStream != null)
                _soundStream.Dispose();

            if(_sourceVoice != null && _sourceVoice.IsValueCreated)
                _sourceVoice.Value.Dispose();
        }
    }
}